Программа DelegateAccount иллюстрирует использование делегатов на примере банковского счета. В файле DelegateAccount. cpp объявляется делегат NotifyCallback. Методы, соответствующие по сигнатурам методам, описанным в объявлении делегата, реализованы в классе DelegateAccount. Метод Мат (Главный) создает экземпляры делегатов и объединяет их различными способами. Указатель на экземпляр делегата передается экземпляру класса Account (Счет), который использует инкапсулированные делегатом методы для выдачи соответствующего ситуации сообщения об овецдрафте.
Обратим внимание на динамичную и гибкую связь между этими объектами. Класс Account (Счет) не знает, какой из методов будет использоваться для выдачи сообщения в случае овердрафта. Он просто вызывает делегат, который по очереди вызывает все методы из списка, причем адаптацию списка можно производить и в процессе выполнения программы.
Приведем исходный код класса Account (Счет):
//Account.h
_delegate void NotifyCallback(Decimal balance); // делегировать
NotifyCallback (Десятичный баланс);
_gc class Account
// класс сборщика мусора Счет
{
Приведем исходный код объявления и тестирования делегата:
//DelegateAccount.h
_gc class DelegateAccount
// класс сборщика мусора DelegateAccount
{
public:
static void Main() // Главный
{
// создать делегат для статического метода NotifyCustomer
NotifyCallback *pCustDlg = new NotifyCallback(
О, // ноль для статического метода NotifyCustomer
NotifyCustomer);
// создать делегат для статического метода NotifyBank
NotifyCallback *pBankDlg = new NotifyCallback(
О, // ноль для статического метода NotifyBank
NotifyBank);
// объявить, что делегат-объект используется // объектом Account
NotifyCallback *pCurrDlg;
// псевдокод: pCurrDlg = pCustDlg + pBankDlg pCurrDlg = static_cast<NotifyCallback
*>(
Delegate::Combine(pCustDlg, pBankDlg)); // Делегат:
// Объединение
// создать объект Account и установить
// делегат для использования
Account *рАсс = new Account(100, pCurrDlg); // новый Счет
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance()));
// баланс
// вызвать делегат два раза
pAcc->Withdraw(125); // обратный вызов через делегат!
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance()));
// баланс
pAcc->Deposit(200);// Депозит
pAcc->Withdraw(125);
// кредит по текущему счету не нужен, // так что не вызывать
обратно
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance()));
// баланс
// альтернатива: pCurrDlg - = pBankDlg
pCurrDlg = static_cast<NotifyCallback *>(
Delegate::Remove(pCurrDlg, pBankDlg)); // Делегат::
// Удалить
// установить новый делегат, который используется
// объектом Account
pAcc->SetDelegate(pCurrDlg);
// вызвать делегат
pAcc->Withdraw(125); // обратный вызов через делегат!
// создать экземпляр, требуемый для экземпляра делегата DelegateAccount
*pda = new DelegateAccount();
// создать делегат для экземпляра метода Notifylnstance NotifyCallback
*p!nstDlg = new NotifyCallback(
pda, // отличный от нуля для метода Notifylnstance
Notifylnstance);
// дополнительный код: pCurrDlg + = plnstDlg
pCurrDlg = static_cast<NotifyCallback *>(
Delegate::Combine(pCurrDlg, plnstDlg)); // Делегат:
// Объединение
// установить новый делегат, который используется
// объектом Account pAcc->SetDelegate(pCurrDlg);
pAcc->Withdraw(125); // обратный вызов через делегат!
}
private: // частный
static void NotifyCustomer(Decimal balance) // Десятичный
// баланс
{
Console::WriteLine("Dear customer,"); // Дорогой клиент,
Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет
превышен,
// баланс
_box(balance)); // баланс
}
static void NotifyBank(Decimal balance) // Десятичный баланс
{
Console::WriteLine("Dear bank,"); // Дорогой банк,
Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет
превышен,
// баланс
_box(balance)); // баланс
}
void Notifylnstance(Decimal balance) // Десятичный баланс
{
Console::WriteLine("Dear instance,"); // Дорогой
// представитель
Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет
превышен,
// баланс
_box(balance)); // баланс
}
};
Ниже приведен результат работы программы. Обратите внимание на то, какие методы вызываются в зависимости от операций, выполняемых делегатом на каждом этапе.
balance = 100
Dear customer,
Account overdrawn, balance = -25
Dear bank,
Account overdrawn, balance = -25
balance = -25
balance = 50
Dear customer,
Account overdrawn, balance = -75
Dear customer,
Account overdrawn, balance = -200
Dear instance,
Account overdrawn, balance = -200
А вот и перевод выдачи:
баланс = 100 Дорогой клиент,
Овердрафт по счету, баланс =-25
Дорогой банк,
Овердрафт по счету, баланс =-25
баланс =-25
баланс = 50
Дорогой клиент,
Овердрафт по счету, баланс =-75
Дорогой клиент,
Овердрафт по счету, баланс =-200
Дорогой представитель,
Овердрафт по счету, баланс =-200